// 为防止环形队列的index出现溢出，应该在index到最大值的时候进行reindex
struct cycle {
  uint8_t read;
  uint8_t write;
  int arr[16];
  int max = 127;
  int length = 8;
  void re_indx() {
    read = read % length;
    write = write % length;
    // write是不可能小于read的，出现这种情况只能是write写完n圈后又开始，
    // 而read还在n- 1圈的某个位置
    if (write < read) {
      write = write + length;
    }
  }
};

struct BuffUnit {
  long long vol;
  int ask;
  long long asize;
  int bid;
  long long bsize;
  int idx = 0;

  BuffUnit() {
    vol = 0;
    ask = 0;
    asize = 0;
    bid = 0;
    bsize = 0;
    idx = 0;
  }
  void reset() {
    vol = 0;
    ask = 0;
    asize = 0;
    bid = 0;
    bsize = 0;
  }
  BuffUnit(const BuffUnit &unit) {
    vol = unit.vol;
    ask = unit.ask;
    asize = unit.asize;
    bid = unit.bid;
    bsize = unit.bsize;
    idx = unit.idx;
  }

  BuffUnit &operator=(const BuffUnit &unit) {
    vol = unit.vol;
    ask = unit.ask;
    asize = unit.asize;
    bid = unit.bid;
    bsize = unit.bsize;
    idx = unit.idx;
    return *this;
  }
};

unsigned int max_widx = 0;
unsigned int max_ridx = 0;

template <typename T>
struct identity {
  typedef T type;
};

template <typename T>
class VectorSized {
 public:
  template <typename N>
  void fills() {
    fill_detail(identity<N>());
  }

  template <typename N>
  void fill_detail(identity<N>) {}

  void fill_detail(identity<int>) { fill(data.begin(), data.end(), 0); }

  void fill_detail(identity<double>) { fill(data.begin(), data.end(), 0); }

  void fill_detail(identity<BuffUnit>) {
    BuffUnit zero;
    memset(&zero, 0, sizeof(zero));
    fill(data.begin(), data.end(), zero);
  }

  string ticker;
  vector<T> data;
  // private:
  size_t write_idx;
  size_t read_idx;
  int size;

 public:
  VectorSized(const int &p_size = 0) {
    write_idx = 0;
    read_idx = 0;
    size = p_size == 0 ? VECTOR_SIZED : p_size;
    data.resize(size);
    //  fun<T>();
    // fills(data.begin(), data.end(), 0);
    fills<T>();
  }

  void push(const T &t) {
    if (write_idx < size) {
      data[write_idx++] = t;
    } else {
      realloc();
      data[write_idx++] = t;
    }
  }
  size_t get_write_idx() { return write_idx; }
  void realloc() {
    vector<T> temp;
    temp.resize(size);
    for (int i = 0; i < size; i++) {
      temp[i] = data[i];
    }

    data.resize(2 * size);

    for (int j = 0; j < size; j++) {
      data[j] = temp[j];
    }
    size = 2 * size;
  }
};

class CycleVector {
  // private:
 public:
  vector<BuffUnit> buf_vec;
  size_t read_idx;  // size_t  enough for a ticker
  size_t write_idx;
  size_t pre_read;

  long long vol_925;
  unsigned size;

 public:
  string ticker;
  int pre_vol;
  CycleVector(const int &p_size = 0) {
    read_idx = 0;
    write_idx = 0;
    pre_read = 0;
    vol_925 = 0;
    pre_vol = 0;
    size = p_size == 0 ? UPDATE_SIZE : p_size;
    buf_vec.resize(size);
  }
  // 数据溢出情况要怎么处理  即write_idx 不能++了，
  // 但是仍然要推数据，对vector扩容
  void push(const BuffUnit &line) {
    if (write_idx - read_idx < size) {
      buf_vec[mod(write_idx)] = line;
      write_idx++;
    } else {
      cout << "buffer overflow , need  realloc " << ticker << "[widx]"
           << write_idx << "[read_idx]" << read_idx << endl;
      realloc();
      buf_vec[mod(write_idx)] = line;
      write_idx++;
    }
    max_widx = write_idx > max_widx ? write_idx : max_widx;
  }
  // realloc时 元素的移动顺序为 readidx -> size 和  0 ->readidx-1 ,再置writeidx
  // = size, readidx = 0,
  void realloc() {
    vector<BuffUnit> temp;
    temp.resize(buf_vec.size());
    // 先将 readidx -> size-1的值移动到 temp 中
    size_t idx = 0;
#ifdef WHERE_SEG
    cout << "[realloc  pos 1]"
         << "[read]" << read_idx << "[write_idx]" << write_idx << endl;
#endif

    for (size_t j = read_idx; j < buf_vec.size(); idx++, j++) {
      temp[idx] = buf_vec[j];
    }
#ifdef WHERE_SEG
    cout << "[realloc pos 2]"
         << "[read]" << read_idx << "[write_idx]" << write_idx << endl;
#endif

    // 再将0 ->readidx-1的值移到 temp中      idx<temp.size() 是需要的
    for (size_t k = 0; k < read_idx && idx < temp.size(); k++) {
      temp[idx++] = buf_vec[k];
    }

    buf_vec.resize(buf_vec.size() * 2);

#ifdef WHERE_SEG
    cout << "[realloc pos 3]"
         << "[read]" << read_idx << "[write_idx]" << write_idx << endl;
#endif
    for (size_t i = 0; i < temp.size(); i++) {
      buf_vec[i] = temp[i];
    }
    read_idx = 0;
    write_idx = size;
    size = size * 2;

#ifdef WHERE_SEG
    cout << "[after realloc]"
         << "[read]" << read_idx << "[write_idx]" << write_idx << endl;
#endif
  }
  // 注意read_idx 类型的一致 否则容易出现segment fault
  inline int mod(size_t x) noexcept { return x % size; }

  /// -1 r==w ,  0 match vol ,   1 cant match vol, return left value ,  2 cant
  /// match vol, return right value
  const int get_max_vol() { return buf_vec[mod(write_idx - 1)].vol; }
  const BuffUnit back() { return buf_vec[mod(write_idx - 1)]; }
  pair<BuffUnit, int> find(const int &vol, const int pos = 0, const int cnt = 0,
                           const int is_second = 0) {
#ifdef WHERE_SEG
    cout << "[curr find vol]" << vol << "[read]" << read_idx << "[write_idx]"
         << write_idx << "[ticker_in_cycle]" << ticker << "[max_vol]"
         << buf_vec[mod(write_idx - 1)].vol << endl;
#endif
    BuffUnit ex;
    ex.vol = -1;
    pre_read = read_idx;
    for (;;) {
#ifdef WHERE_SEG
      if (ticker == "159885") {
        cout << "[special read]" << read_idx << "[write_idx]" << write_idx
             << "[pos]" << pos << "[cnt]" << cnt << "[is_seconds]" << is_second
             << "[vol]" << vol << "[size]" << size << "[buf_vec.size]"
             << buf_vec.size() << endl;
        //  int cnt = 0;
        //  for(int i= read_idx; cnt<10 && i < buf_vec.size(); i++){
        //          std::cout<<"[buf_vec value]"<< buf_vec[ mod(i)].vol <<"[i]"
        //          << i  <<endl; cnt++;
        //  }
      }
#endif

      if (read_idx == write_idx) return {ex, -1};
      // int  curr = buf_vec[read_idx++%size].vol;

      int curr = buf_vec[mod(read_idx)].vol;
      if (curr < vol) {
        read_idx++;
        max_ridx = read_idx > max_ridx ? read_idx : max_ridx;
        continue;
      }
      if (curr == vol) {
        read_idx++;
#ifdef WHERE_SEG
        buf_vec[mod(read_idx - 1)].idx = mod(read_idx - 1);
#endif
        return {buf_vec[mod(read_idx - 1)], 0};
      }
      // 即read_idx 已经移到了比snap成交量大的情况，这种情况的处理方式
      if (curr > vol) {
        int l_diff = vol - buf_vec[mod(read_idx - 1)].vol;
        int r_diff = curr - vol;
        size_t curr_read = read_idx;
        ////可能会超前，然后一直错位,这里考虑--
        read_idx = read_idx-- > 0 ? read_idx : 0;
        if (l_diff < r_diff) {
#ifdef WHERE_SEG
          buf_vec[mod(curr_read - 1)].idx = mod(curr_read - 1);
#endif
          return {buf_vec[mod(curr_read - 1)], 1};

        } else {
#ifdef WHERE_SEG
          buf_vec[mod(curr_read)].idx = mod(curr_read);
#endif
          return {buf_vec[mod(curr_read)], 2};
        }
      }
    }
  }
};
